using Vin.Event;
using Vin.Extension.Framework.Implement;
using Vin.Extension.Framework.Quartz.Dto.Entities;
using Vin.Extension.Framework.Quartz.Dto.List;
using Vin.Extension.Framework.Quartz.Entities;
using Vin.Extension.Framework.Quartz.EventArgs;
using Vin.Extension.Framework.Quartz.Repository;
using Vin.Extension.Framework.Quartz.ServiceInterface;
using Vin.Extension.Framework.Repository;
using Vin.Tool.Attributes;
using Vin.Tool.Core.AssemblyCategory;
using Vin.Tool.Core.AssertCategory;

namespace Vin.Extension.Framework.Quartz.Service;

public class SysJobService : VinFrameworkBaseRecordServiceAsync<SysJobDto, SysJobListDto, SysJobRepository,
    SysJob>, ISysJobService
{
    [Inject] private readonly ISysJobGroupService _sysJobGroupService = null!;

    #region 重写

    public override Task<List<SysJobDto>> ListAsync(SysJobListDto dto)
    {
        return base.ListAsync(dto,
            CreateExpressionable()
                .AndIF(dto.GroupId.HasValue, m => m.GroupId == dto.GroupId)
                .AndIF(dto.Keyword.IsNotNullOrEmpty(), m => m.Name!.Contains(dto.Keyword!))
        );
    }

    public override async Task<SysJobDto?> SaveReturnDataAsync(SysJobDto dto)
    {
        var group = await _sysJobGroupService.QueryOrCreateByNameAsync(dto.GroupName!);
        dto.GroupId = group.Id;
        return await base.SaveReturnDataAsync(dto, SaveCallback);
    }

    public override async Task<bool> DelAsync(long id)
    {
        var job = await QueryAsync(id);
        if(job == null) return false;

        var result = await base.DelAsync(id);

        // 删除任务
        VinEventManager.Fire<VinRemoveJobEventArg>(this, new VinRemoveJobEventArg(id, job!.GroupId!.Value));

        return result;
    }

    #endregion

    #region 实现

    public async Task<bool> StartAsync(long id)
    {
        // 修改任务状态
        await _baseRepository.ExecuteUpdateableAsync(new SysJob()
        {
            Status = JobStatus.Running,
            CompletedLoopCount = 0,
            ErrorCount = 0
        }, m => m.Id == id);

        // 启动任务
        VinEventManager.Fire<VinStartJobEventArg>(this, new VinStartJobEventArg(id));

        return true;
    }

    public async Task<bool> StopAsync(long id)
    {
        var job = await QueryAsync(id);
        if (job == null) return false;
        
        await _baseRepository.ExecuteUpdateableAsync(new SysJob()
        {
            Status = JobStatus.Stop
        }, m => m.Id == id);

        // 删除任务
        VinEventManager.Fire<VinRemoveJobEventArg>(this, new VinRemoveJobEventArg(id, job.GroupId!.Value));

        // 修改任务状态
        return true;
    }

    public async Task<List<SysJobDto>> RunningListAsync()
    {
        return await ListAllAsync(CreateExpressionable().And(m => m.Status == JobStatus.Running), false);
    }

    #endregion

    #region 保存之前的回调

    public Task SaveCallback(SaveType saveType, SysJob job)
    {
        if (job.ExecuteType == JobExecuteType.Generics)
        {
            var type = AssemblyTool.GetVinTypes.FirstOrDefault(m => m.FullName == job.ClassName);
            EmptyTool.CheckIsNullOrEmpty(type, "未找到对应的类型");
            job.AssemblyName = type?.Assembly.GetName().Name;
        }

        if (job.LoopType == JobLoopType.Once)
        {
            job.LoopCount = 1;
        }

        return Task.CompletedTask;
    }

    #endregion
}